using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Data.SqlClient;
using Microsoft.ApplicationBlocks.Data;
using System.Data;

namespace Microsoft.SharedSource.SqlServer.MDDE.Repository
{
    public sealed class InstanceColumnProperty
    {
        #region Fields

        InstanceColumn parentColumn;
        string name;
        string value;

        #endregion

        #region Properties

        public InstanceColumn ParentColumn
        {
            get { return parentColumn; }
        }

        public string Name
        {
            get { return name; }
        }

        public string Value
        {
            get { return this.value; }
            set { this.value = value; }
        }

        #endregion

        #region Methods
        public InstanceColumnProperty(
            InstanceColumn parentColumn, string propertyName)
            : this(parentColumn, propertyName, null) { }

        public InstanceColumnProperty(
            InstanceColumn parentColumn, string propertyName, SqlTransaction txn)
        {
            this.parentColumn = parentColumn;
            this.name = propertyName;

            // Get the property value from repository.
            SqlParameter[] sqlParams = new SqlParameter[2];
            sqlParams[0] =
                new SqlParameter("columnId",
                parentColumn.Id);
            sqlParams[1] = new SqlParameter("propertyName",
                this.Name);

            DataSet propertyInfo;
            if (txn == null)
                propertyInfo =
                SqlHelper.ExecuteDataset(
                parentColumn.ParentCollection.ParentComponent.ParentInstance.
                ParentTemplate.ParentRepository.RepositoryConnection,
                CommandType.Text,
                Resource.GetColumnPropertyInfo, sqlParams);
            else
                propertyInfo =
                SqlHelper.ExecuteDataset(txn,
                CommandType.Text,
                Resource.GetColumnPropertyInfo, sqlParams);

            // Return if we find nothing.
            if (propertyInfo.Tables[0].Rows.Count == 0)
                return;

            // Otherwise, set the property info.
            this.value =
                propertyInfo.Tables[0].Rows[0]["PropertyValue"].ToString();

        }

        internal void Create(SqlTransaction inputTxn)
        {
            // Create a new transaction if there is no input transaction.
            SqlTransaction txn = inputTxn != null ? inputTxn :
                parentColumn.ParentCollection.ParentComponent.
                ParentInstance.ParentTemplate.ParentRepository.
                RepositoryConnection.BeginTransaction();

            try
            {
                SqlParameter[] sqlParams = new SqlParameter[3];
                sqlParams[0] =
                    new SqlParameter("columnId", parentColumn.Id);
                sqlParams[1] =
                    new SqlParameter("propertyName", this.Name);
                sqlParams[2] =
                    new SqlParameter("propertyValue", this.Value);

                SqlHelper.ExecuteNonQuery(txn,
                    CommandType.StoredProcedure,
                    "sp_CreateInstanceColumnProperty",
                    sqlParams);

                // Commit the transaction if it is not an input one.
                if (inputTxn == null)
                    txn.Commit();
            }
            catch (Exception ex)
            {
                // Rollback the transaction if it is not an input one.
                if (inputTxn == null)
                    txn.Rollback();
                throw ex;
            }
        }

        internal void Delete(SqlTransaction txn)
        {
            // Delete property.
            SqlParameter[] sqlParams = new SqlParameter[2];
            sqlParams[0] = new SqlParameter(
                "columnId", parentColumn.Id);
            sqlParams[1] = new SqlParameter(
                "propertyName", this.Name);

            SqlHelper.ExecuteNonQuery(txn,
                CommandType.StoredProcedure,
                "sp_DeleteInstanceColumnProperty",
                sqlParams);
        }

        internal void Update(SqlTransaction txn)
        {
            SqlParameter[] sqlParams = new SqlParameter[3];
            sqlParams[0] =
                new SqlParameter("columnId", parentColumn.Id);
            sqlParams[1] =
                new SqlParameter("propertyName", this.Name);
            sqlParams[2] =
                new SqlParameter("propertyValue", this.Value);

            SqlHelper.ExecuteNonQuery(txn,
                CommandType.StoredProcedure,
                "sp_UpdateInstanceColumnProperty",
                sqlParams);
        }

        #endregion

        internal void ApplyProperties(System.Xml.XmlNode xProperty)
        {
            this.value = xProperty.Attributes["Value"].Value;
        }
    }

    public sealed class InstanceColumnPropertyCollection : IEnumerable
    {
        #region Fields

        private Dictionary<string, InstanceColumnProperty>
            columnProperties =
            new Dictionary<string, InstanceColumnProperty>();
        InstanceColumn parentColumn;

        #endregion

        #region Properties

        public int Count
        {
            get { return columnProperties.Count; }
        }

        public InstanceColumn ParentColumn
        {
            get { return parentColumn; }
        }

        public InstanceColumnProperty this[string propertyName]
        {
            get { return columnProperties[propertyName]; }
        }

        #endregion

        #region Methods

        internal InstanceColumnPropertyCollection(
            InstanceColumn parentColumn)
        {
            this.parentColumn = parentColumn;
        }

        public void Add(InstanceColumnProperty columnProperty)
        {
            columnProperties.Add(
                columnProperty.Name, columnProperty);
        }

        public void Remove(InstanceColumnProperty columnProperty)
        {
            columnProperties.Remove(columnProperty.Name);
        }

        public void Clear()
        {
            columnProperties.Clear();
        }

        public bool ContainsProperty(string propertyName)
        {
            return columnProperties.ContainsKey(propertyName);
        }

        #endregion

        #region IEnumerable Members

        public IEnumerator GetEnumerator()
        {
            return columnProperties.Values.GetEnumerator();
        }

        #endregion
    }
}
